package com.sj.controller;

import com.sj.common.lang.ApiResult;
import com.sj.common.lang.Const;
import com.sj.entity.Role;
import com.sj.entity.ThirdPartyKnowRelation;
import com.sj.entity.User;
import com.sj.entity.UserRole;
import com.sj.service.RoleService;
import com.sj.service.ThirdPartyKnowRelationService;
import com.sj.service.UserRoleService;
import com.sj.service.UserService;
import com.sj.utils.JwtUtils;
import com.sj.utils.RedisUtils;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthQqRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 第三方登录
 *
 * @author xiaoqi
 */
@RestController
@RequestMapping("/oauth")
public class JustAuthController {

    @Value("${know.tokenKey}")
    private String userTokenKey;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private ThirdPartyKnowRelationService thirdPartyKnowRelationService;

    @Autowired
    private UserService userService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserRoleService userRoleService;

    @Value("${know.init.password}")
    private String initPassword;

    /**
     * 获取授权链接并跳转到第三方授权页面
     *
     * @param response response
     * @throws IOException response可能存在的异常
     */
    @RequestMapping("/render")
    public ApiResult renderAuth(HttpServletResponse response) throws IOException {
        AuthRequest authRequest = getAuthRequest();
        String token = AuthStateUtils.createState();
        String authorizeUrl = authRequest.authorize(token);
        return ApiResult.success("qq登录", authorizeUrl);
    }


    /**
     * 用户在确认第三方平台授权（登录）后， 第三方平台会重定向到该地址，并携带code、state等参数
     *
     * @param callback 第三方回调时的入参
     * @return 第三方平台的用户信息
     */
    @RequestMapping("/connect")
    public void login(AuthCallback callback, HttpServletResponse response) throws IOException, ServletException {
        AuthRequest authRequest = getAuthRequest();
        AuthResponse<AuthUser> login = authRequest.login(callback);
        String uuid = login.getData().getUuid();
        String username = login.getData().getUsername();
        String nickname = login.getData().getNickname();
        String avatar = login.getData().getAvatar();
        // 首先判断关联表中是否有该uuid
        ThirdPartyKnowRelation one = thirdPartyKnowRelationService.lambdaQuery().eq(ThirdPartyKnowRelation::getQqUnionId, uuid).one();
        User user = null;
        if (one != null) {
            // 如果有 直接查询用户
            user = userService.getById(one.getUserId());
            user.setUsername(username);
            userService.updateById(user);
        } else {
            // 如果没有 先创建用户
            user = User.builder().username(username).nickname(nickname).avatarUrl(avatar).password(initPassword).build();

            user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
            boolean result = userService.save(user);
            user.setPassword(null);
            if (result) {
                // 添加普通用户角色
                Role role = roleService.lambdaQuery().eq(Role::getCode, Const.USER).one();
                UserRole build = UserRole.builder().userId(user.getId()).roleId(role.getId()).build();
                userRoleService.save(build);
            }
            thirdPartyKnowRelationService.save(ThirdPartyKnowRelation.builder().qqUnionId(uuid).userId(user.getId()).build());
        }

        String token = jwtUtils.generateToken(user.getId() + "-" + user.getUsername());
        String authorities = userService.getAuthorities(user.getId(), user.getUsername());
        user.setPassword(null);
        redisUtils.set(userTokenKey + "-" + user.getUsername(), token, jwtUtils.getExpire());
        response.sendRedirect("http://sjun7.com/qqlogin?authorities=" + authorities + "&token=" + token + "&uid=" + user.getId());
    }


    /**
     * 获取授权Request
     *
     * @return AuthRequest
     */
    private AuthRequest getAuthRequest() {
        return new AuthQqRequest(AuthConfig.builder()
                .clientId("102015495")
                .clientSecret("Sq33qRoyve8YnobA")
                .redirectUri("http://api-know.sjun7.com/oauth/connect")
                .unionId(true)
                .build());
    }
}

